package indi.lqzhi.component.picker;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.VectorDrawable;
import android.util.AttributeSet;
import android.util.Size;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.ColorInt;
import androidx.annotation.DrawableRes;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;

import indi.lqzhi.component.R;

public class SoundPicker extends View {

    /**
     * 默认尺寸：450
     */
    private static final int DEFAULT_SIZE = 450;
    /**
     * TAG
     */
    private static final String TAG = "SoundPicker";
    /**
     * 整个控件的宽度
     */
    private int width;
    /**
     * 整个控件的高度
     */
    private int height;
    /**
     * 内圆的半径
     */
    private float innerRadius;
    /**
     * 外圆的半径
     */
    private float outerRadius;
    /**
     * 中心圆半径
     */
    private float centerRadius;
    /**
     * 圆的圆心坐标
     */
    private float circleX, circleY;

    /**
     * 当前音量的值
     * 在0~100之间
     */
    private int volumeValue;
    /**
     * 是否为静音状态
     */
    private boolean isMute;

    /**
     * 是否为滑动调整状态
     */
    private boolean isAdjust;

    /**
     * 音频字体大小
     */
    private float valueSize;

    /**
     * 音频字体类型
     */
    private Typeface valueTypeFace;

    /**
     * 圆环颜色
     */
    private int cirqueColor;
    /**
     * 指示器颜色
     */
    private int indicatorColor;
    /**
     * 指示器背景颜色
     */
    private int indicatorBackgroundColor;
    /**
     * 静音颜色
     */
    private int muteColor;
    /**
     * 非静音颜色
     */
    private int unmuteColor;
    /**
     * 音量文字颜色
     */
    private int valueColor;
    /**
     * 长条颜色
     */
    private int markColor;

    /**
     * 静音图标
     */
    private Bitmap muteBitmap;
    /**
     * 非静音图标
     */
    private Bitmap unmuteBitmap;

    /**
     * 圆环画笔
     */
    private Paint cirquePaint;
    /**
     * 指示器画笔
     */
    private Paint indicatorPaint;
    /**
     * 指示器背景画笔
     */
    private Paint indicatorBackgroundPaint;
    /**
     * 中心图标画笔
     */
    private Paint centerBitmapPaint;
    /**
     * 长条指示器画笔
     */
    private Paint markPaint;

    /**
     * 静音状态改变的监听器
     */
    public interface OnStateChangeListener{
        void onStateChange(boolean isMutx);
    }

    /**
     * 音量状态改变的监听器
     */
    public interface OnVolumeChangeListener{
        void onVolumeChange(int volume);
    }

    private OnStateChangeListener onStateChangeListener;

    private OnVolumeChangeListener onVolumeChangeListener;


    public SoundPicker(Context context) {
        this(context, null, 0);
    }

    public SoundPicker(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SoundPicker(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SoundPicker);
        this.volumeValue = (typedArray.getInt(R.styleable.SoundPicker_sound_default_value, 0) % 101);
        this.isMute = typedArray.getBoolean(R.styleable.SoundPicker_sound_default_mute, false);
        this.cirqueColor = typedArray.getColor(R.styleable.SoundPicker_sound_cirque_color, 0xffe6e6e6);
        this.indicatorColor = typedArray.getColor(R.styleable.SoundPicker_sound_indicator_color, 0xff1c74f3);
        this.indicatorBackgroundColor = typedArray.getColor(R.styleable.SoundPicker_sound_indicator_background_color, 0xffe6e6e6);
        this.valueColor = typedArray.getColor(R.styleable.SoundPicker_sound_value_color, 0xfff3f781);
        this.muteColor = typedArray.getColor(R.styleable.SoundPicker_sound_mute_color, 0xff1c74f3);
        this.unmuteColor = typedArray.getColor(R.styleable.SoundPicker_sound_unmute_color, 0xffe6e6e6);
        this.markColor = typedArray.getColor(R.styleable.SoundPicker_sound_mark_color, 0xff1c74f3);
        this.valueSize = typedArray.getDimension(R.styleable.SoundPicker_sound_value_size,sp2px(18));
        int muteResId = typedArray.getResourceId(R.styleable.SoundPicker_sound_mute_src, R.drawable.ic_music_on); //获取 图片资源id
        int unmuteResId = typedArray.getResourceId(R.styleable.SoundPicker_sound_unmute_src, R.drawable.ic_music_off); //获取 图片资源id
        this.muteBitmap = resToBitmap(muteResId, muteColor);
        this.unmuteBitmap = resToBitmap(unmuteResId, unmuteColor);
        initPicker();
        typedArray.recycle();
    }

    /**
     * 初始化选择器
     */
    private void initPicker() {
        //初始化画笔
        cirquePaint = new Paint();//圆环画笔
        cirquePaint.setColor(cirqueColor);//圆环颜色

        centerBitmapPaint = new Paint();//中心图标画笔、颜色等画的时候决定

        indicatorBackgroundPaint = new Paint();//指示器背景画笔
        indicatorBackgroundPaint.setColor(indicatorBackgroundColor);
        indicatorBackgroundPaint.setStyle(Paint.Style.STROKE);
        indicatorBackgroundPaint.setStrokeWidth(15);//默认背景为35px
        indicatorBackgroundPaint.setAntiAlias(true);//取消锯齿

        indicatorPaint = new Paint();//指示器画笔
        indicatorPaint.setColor(indicatorColor);
        indicatorPaint.setStyle(Paint.Style.STROKE);
        indicatorPaint.setStrokeCap(Paint.Cap.ROUND);
        indicatorPaint.setStrokeWidth(35);//默认指示器宽度为35
        indicatorPaint.setAntiAlias(true);//取消锯齿

        markPaint = new Paint();//长条画笔
        markPaint.setColor(markColor);
        markPaint.setStrokeWidth(20);//指示器宽度为20
        markPaint.setStrokeCap(Paint.Cap.ROUND);
        markPaint.setAntiAlias(true);//取消锯齿

        valueTypeFace = Typeface.DEFAULT_BOLD;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getMeasureSize(widthMeasureSpec);
        height = getMeasureSize(heightMeasureSpec);
        final int min = Math.min(width, height);//保证控件为方形
        setMeasuredDimension(min, min);
        //四边最保留区域（非绘图区，最少保留4给像素）
        int paddingLeft = (getPaddingStart() == 0 ? getPaddingLeft() : getPaddingStart()) + 12;
        int paddingRight = (getPaddingEnd() == 0 ? getPaddingRight() : getPaddingEnd()) + 12;
        int paddingTop = getPaddingTop() + 12;
        int paddingBottom = getPaddingBottom() + 12;
        int size = (int) (Math.min((width - paddingLeft - paddingRight), (height - paddingTop - paddingBottom)) / 1.25); //选择最小
        circleX = paddingLeft + (width - paddingLeft - paddingRight) / 2.0f;//(width+getPaddingLeft()-getPaddingRight()) / 2;  //确定圆的x坐标中心点
        circleY = paddingTop + (height - paddingTop - paddingBottom) / 2.0f;//height / 2;   //确定圆的Y坐标中心点
        //分辨率适配:获取圆环的宽度 圆环的半径 内部圆的半径
        outerRadius = size / 2f;//-dp2px(getContext(),4);//-barWidth*2;
        innerRadius = outerRadius - 30 - 30; //30为圆环宽度
        centerRadius = innerRadius / 2;
    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        /***********************画圆环*****************************/
        Path path = new Path();
        RectF outerRect = new RectF(circleX - outerRadius, circleY - outerRadius, circleX + outerRadius, circleY + outerRadius);
        RectF innerRect = new RectF(circleX - innerRadius, circleY - innerRadius, circleX + innerRadius, circleY + innerRadius);
        path.addArc(outerRect, 0, 360);
        path.arcTo(innerRect, 359, -360);
        path.close();
        canvas.drawPath(path, cirquePaint);
        /***********************画指示器背景*****************************/
        RectF rect = new RectF(circleX - outerRadius - 65, circleY - outerRadius - 65, circleX + outerRadius + 65, circleY + outerRadius + 65);
        //设置为360的时候也是这样
        canvas.drawArc(rect, 135, 270, false, indicatorBackgroundPaint);
        /***********************画指示器*****************************/
        int angle = Math.round(volumeValue * 2.7f);
        canvas.drawArc(rect, 135, angle, false, indicatorPaint);
        /***********************画长条*****************************/
        float markSx = (float) (circleX + (innerRadius - 30) * Math.cos(Math.toRadians(angle + 135)));
        float markSy = (float) (circleY + (innerRadius - 30) * Math.sin(Math.toRadians(angle + 135)));
        float markTx = (float) (circleX + (innerRadius - 30 - (centerRadius / 1.75)) * Math.cos(Math.toRadians(angle + 135)));
        float markTy = (float) (circleY + (innerRadius - 30 - (centerRadius / 1.75)) * Math.sin(Math.toRadians(angle + 135)));
        canvas.drawLine(markSx, markSy, markTx, markTy, markPaint);
        /***********************画中心内容*****************************/
        int imgRadius = (int) (centerRadius / 2);
        if (isAdjust) {
            String s = String.valueOf(volumeValue);
            //当前状态为调整状态,中心点画数字
            centerBitmapPaint.setColor(Color.BLACK);//修改为文字颜色
            centerBitmapPaint.setTextSize(valueSize);//设置文字大小
            centerBitmapPaint.setTypeface(valueTypeFace);
            Size textSizePx = getTextSizePx(s,valueSize,valueTypeFace);
            canvas.drawText(s, circleX - (textSizePx.getWidth() / 2.0f), circleY + (textSizePx.getHeight() / 2.0f) , centerBitmapPaint);//centerBitmapPaint
            return;
        }
        if (isMute) {
            //当前为静音状态
            centerBitmapPaint.setColor(muteColor);
            if (muteBitmap != null)
                canvas.drawBitmap(muteBitmap, null, new Rect((int) (circleX - imgRadius), (int) (circleY - imgRadius), (int) (circleX + imgRadius), (int) (circleY + imgRadius)), centerBitmapPaint);//centerBitmapPaint
        } else {
            centerBitmapPaint.setColor(unmuteColor);
            if (unmuteBitmap != null)
                canvas.drawBitmap(unmuteBitmap, null, new Rect((int) (circleX - imgRadius), (int) (circleY - imgRadius), (int) (circleX + imgRadius), (int) (circleY + imgRadius)), centerBitmapPaint);//centerBitmapPaint
        }
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        int sX = getTop();//获取x的坐标
        int sY = getLeft();//获取y的坐标
        int tX = sX + width;//获取右下角坐标
        int tY = sY + height;//获取右下角坐标
        //容器范围
        float touchX = event.getX();//得到触摸的X
        float touchY = event.getY();//得到触摸的Y
        if ((touchX >= sX && touchX <= tX) && (touchY >= sY && touchY <= tY)) {
            getParent().requestDisallowInterceptTouchEvent(true); //请求请求所有的视图件禁止接收触摸事件
        }
        return super.dispatchTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: //触摸按下
                //点击判断是否是在圆心范围:内圆半径的一半时，为切换状态
                if (isCircleInside(x, y)) {
                    //是圆内，切换状态
                    changeMuteState();
                    if (onStateChangeListener != null){
                        onStateChangeListener.onStateChange(isMute);
                    }
                } else {
                    //圆外，滑动条
                    changeIndicatorState(x, y);
                }
                break;
            case MotionEvent.ACTION_MOVE: //触摸移动
                if (!isCircleInside(x, y)) {
                    //圆外，滑动条
                    changeIndicatorState(x, y);
                }
                break;
            case MotionEvent.ACTION_UP:  //触摸弹起
                isAdjust = false;
                invalidate();//重新绘画
                if (onVolumeChangeListener != null){
                    onVolumeChangeListener.onVolumeChange(volumeValue);
                }
                break;
            case MotionEvent.ACTION_CANCEL: //取消操作
                break;
        }
        return true;
    }

    /**
     * 改变指示条状态
     *
     * @param x 触摸的X点
     * @param y 触摸的Y点
     */
    private void changeIndicatorState(float x, float y) {
        float degrees = (float) ((float) ((Math.toDegrees(Math.atan2(x - circleX, circleY - y)) + 360.0 + 135)) % 360.0);
        //角度四舍五入
        int angle = Math.round(degrees);
        if ((angle > 290 && angle <= 340)) {
            return;
        }
        if (angle >= 270 && angle <= 290) {
            angle = 270;
        }
        if (angle >= 340 && angle <= 360) {
            angle = 0;
        }
        //设置音量转换
        int value = (int) ((10 / 27.0f) * angle);
        updateVolumeValue(value);//设置音量时会自动刷新ui，已经调用了invalidate()方法
        //invalidate(); //刷新ui
    }

    /**
     * 获取测量大小
     */
    private int getMeasureSize(int measureSpec) {
        int result;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;//确切大小,所以将得到的尺寸给view
        } else if (specMode == MeasureSpec.AT_MOST) {
            //默认值为450px,此处要结合父控件给子控件的最多大小(要不然会填充父控件),所以采用最小值
            result = Math.min(DEFAULT_SIZE, specSize);
        } else {
            result = DEFAULT_SIZE;
        }
        return result;
    }


    private void changeMuteState() {
        isMute = !isMute;
        invalidate();//刷新图标
    }

    /**
     * 判断是否在中心圆内
     *
     * @param touchX 触摸点X
     * @param touchY 触摸点Y
     * @return true 在中心圆内 false 在中心圆外
     */
    private boolean isCircleInside(float touchX, float touchY) {
        //根据圆心定义坐标轴
        float x = touchX - circleX;
        float y = circleY - touchY;
        //根据圆内计算公式判断是否在圆内
        double v = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
        return v <= (innerRadius / 2);
    }

    public Bitmap resToBitmap(@DrawableRes int resId, @ColorInt int hint) {
        Drawable drawable = ContextCompat.getDrawable(getContext(), resId);
        if (drawable == null) {
            return null;
        }
        //两种处理方式：第一种，如果是VectorDrawable,则hint颜色生效，如果是BitmapDrawable,则颜色hint颜色不生效
        Canvas canvas = new Canvas();//创建画布
        if (drawable instanceof VectorDrawable) {
            VectorDrawable vectorDrawable = (VectorDrawable) drawable;
            vectorDrawable.setTint(hint);
            //颜色生效
            Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
                    drawable.getIntrinsicHeight(),
                    Bitmap.Config.ARGB_8888);
            canvas.setBitmap(bitmap);
            drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
            drawable.draw(canvas);
            return bitmap;
        } else if (drawable instanceof ColorDrawable) {
            Bitmap mutableBitmap = Bitmap.createBitmap(24,
                    24, Bitmap.Config.ARGB_8888);
            mutableBitmap.eraseColor(muteColor);//填充颜色
            return mutableBitmap;
        } else {
            //颜色不生效
            Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
                    drawable.getIntrinsicHeight(),
                    Bitmap.Config.ARGB_8888);
            canvas.setBitmap(bitmap);
            drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
            drawable.draw(canvas);
            return bitmap;
        }

    }

    public void setVolumeValue(int volumeValue) {
        if (volumeValue < 0 || volumeValue > 100) {
            this.volumeValue = (volumeValue % 100) + 1;
        } else {
            this.volumeValue = volumeValue;
        }
    }

    private void updateVolumeValue(int volumeValue) {
        isAdjust = true;
        setVolumeValue(volumeValue);
        invalidate();//重新绘画
    }

    public int getVolumeValue() {
        return volumeValue;
    }



    public void setValueTypeFace(Typeface valueTypeFace) {
        this.valueTypeFace = valueTypeFace;
    }

    public Typeface getValueTypeFace() {
        return valueTypeFace;
    }

    public OnStateChangeListener getOnStateChangeListener() {
        return onStateChangeListener;
    }

    public void setOnStateChangeListener(OnStateChangeListener onStateChangeListener) {
        this.onStateChangeListener = onStateChangeListener;
    }

    public OnVolumeChangeListener getOnVolumeChangeListener() {
        return onVolumeChangeListener;
    }

    public void setOnVolumeChangeListener(OnVolumeChangeListener onVolumeChangeListener) {
        this.onVolumeChangeListener = onVolumeChangeListener;
    }

    /**
     * Value of sp to value of px.
     *
     * @param spValue The value of sp.
     * @return value of px
     */
    private int sp2px(final float spValue) {
        final float fontScale = Resources.getSystem().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }

    /**
     * 得到文字的大小
     * @param value 文字
     * @param textSize 文字大小 px
     * @param typeface 文字类型
     * @return 大小尺寸
     */
    private Size getTextSizePx(String value,float textSize,Typeface typeface) {
        Paint paint = new Paint();
        paint.setTextSize(textSize);
        paint.setTypeface(typeface);
        Rect rect = new Rect();
        //通过画笔获得文字的边框
        paint.getTextBounds(value, 0, value.length(), rect);
        int textWidth = rect.width();
        int textHeight = rect.height();
        return new Size(textWidth, textHeight);
    }
}
